/*--------------------------------------------------------------------------------
* Copyright (c) 2022,西北农林科技大学信息学院计算机科学系
* All rights reserved.
*
* 文件名称：main.c
* 文件标识：见配置管理计划书
* 摘要：随机生成调查问卷测试样本的演示代码。
* 题目：为设计调查问卷投票结果分析算法，现需要生成投票结果模拟数据。
*       在此，假设仅有单项选择和多项选择两种问卷题型。
*       要求用二进制位表示选择题的一个选项是否被选择，1表示选中，0表示未选中。
*       现要求设计一函数根据选项总数、最少选择数和最多选择项数返回选择结果整数。
*       函数原型要求如下：
*           int get_selected(int tasks, int low, int high);
*       注意：只能按要求完成并提交该函数
*
* 当前版本：1.0
* 作者：耿楠
* 完成日期：2022年12月13日
*
* 取代版本：无
* 原作者：
* 完成日期：
--------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* 如果没有定义RAND_MAX宏，则定义 */
#ifndef RAND_MAX
#  define RAND_MAX ((int) ((unsigned) ~0 >> 1))
#endif

#define TASK_MAX 7

/* 利用位段统计一个字节中1出现的次数 */
#define  sumbites(b) (b.a0+b.a1+b.a2+b.a3+b.a4+b.a5+b.a6+b.a7)

typedef struct
{
    unsigned short a0: 1;
    unsigned short a1: 1;
    unsigned short a2: 1;
    unsigned short a3: 1;
    unsigned short a4: 1;
    unsigned short a5: 1;
    unsigned short a6: 1;
    unsigned short a7: 1;
} TASKSDATA;

/* 函数原型 */
int get_rand_int(int, int);
int get_selected(int, int, int);
void print_selected(int, int);

int main()
{
    /* 置随机种子 */
    srand((unsigned)time(NULL));

    unsigned char sel;

    sel = get_selected(4, 1, 1);

    printf("%d\n", (int)sel);
    print_selected(4, sel);

    sel = get_selected(5, 2, 5);

    printf("%d\n", (int)sel);
    print_selected(5, sel);

    return 0;
}

/* 生成[low, high]之间的随机整数 */
int get_rand_int(int low, int high)
{
    int k;
    double d;

    d = (double) rand() / ((double) RAND_MAX + 1);
    k = (int) (d * (high - low + 1));
    return (low + k);
}

/* 生成选项选择记录整数 */
int get_selected(int tasks, int low, int high)
{
    TASKSDATA p;
    int cnt_ones;
    unsigned char top;
    unsigned char task;

    /* 随机数上限(选项数) */
    top = ((unsigned char) ~0) >> (sizeof(unsigned char) * 8 - tasks);
    /* top = (1 << tasks) - 1; */

    /* 随机数 */
    task = get_rand_int(1, top);
    /* 内存复制 */
    memcpy(&p, &task, sizeof(unsigned char));
    /* 统计1的个数 */
    cnt_ones = sumbites(p);

    /* 选择项数范围判定 */
    while(!(cnt_ones >= low && cnt_ones <= high))
    {
        task = get_rand_int(1, top);
        memcpy(&p, &task, sizeof(unsigned char));
        cnt_ones = sumbites(p);
    }

    return task;
}

/* 输出选择结果 */
void print_selected(int tasks, int sel)
{
    int i;

    for(i = 0; i < tasks - 1; i++)
    {
        printf("item%d\t", i + 1);
    }
    printf("item%d\n", i + 1);

    for(i = 0; i < tasks - 1; i++)
    {
        printf("%d\t", (sel >> i) & 1);
    }
    printf("%d\n", (sel >> i) & 1);
}
